/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package chat.common;

import chat.server.*;
import chat.client.*;
import java.lang.*;
import java.net.*;
import java.io.*;
import java.util.*;

/**
 * Communication bettewen client and server
 * @author berthise
 */
public class Communication extends Thread {

    private String idConnection;
    private DataOutputStream sortie;
    private DataInputStream entree;
    private CommunicationsManager server = null;
    private ChatView client = null;
    private Socket socket;
    private boolean alive;

    /*
     * pour le client
     */
    public Communication(ChatView client, String id, String host, int port) {
        try {
            this.idConnection = id;
            this.client = client;
            /*
             * creation de connection, entree sortie...
             */
            socket = new Socket(host, port);
            OutputStream out = socket.getOutputStream();
            sortie = new DataOutputStream(out);
            InputStream in = socket.getInputStream();
            entree = new DataInputStream(in);
            /*
             * envois d'un message au serveur pour l'avertir de la connexion
             * et du login du client
             */
            Message mess = new Message(Message.CONNECTION, id, "server");
            mess.sendMessage(sortie);

            alive = true;
        } catch (Exception e) {
            System.out.println("error com " + e.toString());
        }
    }

    /*
     * pour le server
     */
    public Communication(CommunicationsManager connections, Socket socket) {
        try {
            this.server = connections;
            this.socket = socket;

            InputStream in = socket.getInputStream();
            entree = new DataInputStream(in);
            OutputStream out = socket.getOutputStream();
            sortie = new DataOutputStream(out);

            alive = true;
        } catch (Exception e) {
            System.out.println("error com " + e.toString());
        }
    }

    /*
     * fermeture du thread en passant le alive a faux (boucle while)
     * fermeture des flux d'entree sortie
     * renvois vrai si tout est bon
     */
    public boolean closeCommunication() {
        try {
            alive = false;
            if (client != null && !socket.isClosed()) {
                Message mess = new Message(Message.DECONNECTION, idConnection, "systemPanel");
                try {
                    mess.sendMessage(sortie);
                } catch (Exception ex) {
                }
                client.writeInfo("Logout OK");
            }
            entree.close();
            sortie.close();
            socket.close();

        } catch (Exception ex) {
//            System.out.println("error close com  " + ex.toString());
            return false;
        }
        return true;
    }

    public void run() {
        while (alive) {
            try {
                receiveMessage();
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                }
            } catch (Exception e) {
                if (client == null) {
                    server.closeCommunication(idConnection);
                } else {
                    client.closeCommunication();
                }
            }
        }
    }

    /*
     * redirige le message sur le flu de sortie de la connection de l'autre
     * C'est provisoir !
     */
    public void sendMessage(String s, String dest) {
        try {
            Message mess = new Message(Message.TEXT, idConnection, dest, s);
            mess.sendMessage(sortie);
        } catch (Exception e) {
            // System.out.println("error send file " + e.toString());
        }
    }
    /*
     * methode appller par la boucle du thread
     * si c'est pour une deconnection, elle transmet au Serveur
     * Sinon, redirection ver la gestion des communications
     */

    public void receiveMessage() throws Exception {
        Message mess = new Message();
        try {
            mess.readMessage(this.entree);
        } catch (Exception e) {
            // System.out.println("error receive mess" + e.toString());
            throw new Exception();
        }
        if (client == null) {
            if (mess.getType() == Message.DECONNECTION) {
                server.closeCommunication(idConnection);
            } else if (mess.getType() == Message.TEXT
                    || mess.getType() == Message.ACK_TEXT) {
                //             System.out.println("redirection message");
                server.redirectionMessage(mess);
            } else if (mess.getType() == Message.FILE || mess.getType() == Message.FILEOK) {
                server.redirectionMessage(mess);
            } else if (mess.getType() == Message.ADD_CHANNEL
                    || mess.getType() == Message.RM_CHANNEL // pas vraiment util
                    || mess.getType() == Message.NEW_CLIENT_CHANNEL
                    || mess.getType() == Message.RM_CLIENT_CHANNEL) {
                server.channelManager(mess, this);
            }
        } else {
            // on a affaire a la gestion des client (et channel)
            if (mess.getType() == Message.LIST
                    || mess.getType() == Message.CONNECTION_CLIENT
                    || mess.getType() == Message.DECONNECTION_CLIENT
                    || mess.getType() == Message.NOTIFY_ADD_CHANNEL
                    || mess.getType() == Message.NOTIFY_RM_CHANNEL) {
                client.notifyList(mess);
            } else if (mess.getType() == Message.FILE) {
                client.sendFile(mess.getMessageStr());
            } else if (mess.getType() == Message.FILE_NON) {
                client.getSendFile(mess.getSrc()).closeSendFile();
            } else if (mess.getType() == Message.FILEOK) {
                // on attend que le contructeur de sendFile est fini !
                client.getSendFile(mess.getSrc()).setReady(true);

            } else {
                if (!client.idTabExist(mess.getSrc())) {
                    client.newChat(mess.getSrc(), false);
                }
                client.writeMessageTab(mess);
            }
        }
    }

    /**
     * getteur est setteur
     * @return
     */
    public String getIdConnection() {
        return idConnection;
    }

    public void setIdConnection(String idConnection) {
        this.idConnection = idConnection;
    }

    public ChatView getClient() {
        return client;
    }

    public void setClient(ChatView client) {
        this.client = client;
    }

    public DataInputStream getEntree() {
        return entree;
    }

    public void setEntree(DataInputStream entree) {
        this.entree = entree;
    }

    public CommunicationsManager getConnections() {
        return server;
    }

    public void setConnections(CommunicationsManager connections) {
        this.server = connections;
    }

    public DataOutputStream getSortie() {
        return sortie;
    }

    public void setSortie(DataOutputStream sortie) {
        this.sortie = sortie;
    }

    public Socket getSocket() {
        return socket;
    }

    public void setSocket(Socket socket) {
        this.socket = socket;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Communication other = (Communication) obj;
        if ((this.idConnection == null) ? (other.idConnection != null) : !this.idConnection.equals(other.idConnection)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 79 * hash + (this.idConnection != null ? this.idConnection.hashCode() : 0);
        return hash;
    }
}
